﻿using System;
using System.Windows.Forms;

using SharpDX;
using SharpDX.Windows;

using DX11Engine;
using SharpDX.DirectInput;
using System.Collections.Generic;
using System.Drawing;

namespace Interface
{
    class Program
    {
        private static J3DObject gilsMesh;

        [STAThread]
        static void Main(string[] args)
        {
            var form = new RenderForm("JDX Engine");
            form.Width = 1024; form.Height = 768;

            JDXRender jRndr = new JDXRender(form); //, false, 1920, 1080);

            J3DObject tri = jRndr.EntityFactory.CreateTriangle(2);
            jRndr.Entities.Add(tri);
            tri.IsVisible = false;

            J3DObject cube = jRndr.EntityFactory.CreateCube();

            cube.Materials = new MeshMaterial[1] { new MeshMaterial() { 
                        TextLayers = new TextureLayer[] { 
                            new TextureLayer() { FileName = "stone.bmp", Type = LayerType.Texture },
                            new TextureLayer() { FileName = "light.bmp", Type = LayerType.LightMap },
                            new TextureLayer() { FileName = "stoneNormals.bmp", Type = LayerType.NormalMap }
                        } } };

            //jRndr.Entities.Add(cube);

            cube.IsVisible = false;

            J3DObject mesh = jRndr.EntityFactory.LoadMQO("test.mqo", .002f);
            jRndr.Entities.Add(mesh);
            mesh.Move(0, 1, -1);
            //mesh.IsVisible = false;

            mesh.Materials = new MeshMaterial[1] { new MeshMaterial() { 
                        TextLayers = new TextureLayer[] { 
                            new TextureLayer() { FileName = "stone.bmp", Type = LayerType.Texture },
                            new TextureLayer() { FileName = "light.bmp", Type = LayerType.LightMap },
                            new TextureLayer() { FileName = "stoneNormals.bmp", Type = LayerType.NormalMap }
                        } } };

            //J3DObject tankMesh = jRndr.EntityFactory.LoadMQO("E:\\metasequoia\\tankTRI.mqo", .01f);
            //jRndr.Entities.Add(tankMesh);

            gilsMesh = jRndr.EntityFactory.LoadGilesMesh("RomanBath.gls", 0.01f);
            jRndr.Entities.Add(gilsMesh);
            //mesh.IsVisible = false;

            J3DObject mesh2 = jRndr.EntityFactory.LoadMQO("AH-64_JDX_TRI.mqo", .003f);
            jRndr.Entities.Add(mesh2);
            mesh2.Move(0, 0.6f, -2.5f);
            //mesh2.IsVisible = false;

            gilsMesh.Move(0, 0, -3);
            tri.Move(3, 0, 0);
            cube.Move(-3, 0, 0);

            CameraViewport cv = jRndr.CameraViewports[0];
            cv.Position = new Vector3(0, 0.5f, -5);

            Jinput inpt = new Jinput(form);
            int framesThisSecond = 0;
            int FPS = 0;
            float timeConstant = 1000;
            double FrameTime = DateTime.Now.Ticks;
            DateTime lastTimeFrame = DateTime.Now;
            // Main loop
            RenderLoop.Run(form, () => {
                if (Convert.ToDecimal(DateTime.Now.Ticks - FrameTime) > 0)
                { timeConstant = Convert.ToSingle((DateTime.Now.Ticks - FrameTime) / 100000); }
                FrameTime = DateTime.Now.Ticks;

                mesh.Rotate(.01f * timeConstant, .02f * timeConstant, .03f * timeConstant);

                mesh2.Rotate(0f, .002f * timeConstant, 0f);
                //Speed = Speed * 0.995f;
                //jRndr.Entities[1].Move(0, 0, Speed * timeConstant);

                //cube.Rotate(.001f, .002f, .004f);

                HandleInput(inpt, form, jRndr, timeConstant);
                jRndr.JRender(cv, System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);

                if (lastTimeFrame < DateTime.Now.Subtract(new TimeSpan(0, 0, 1)))
                {
                    lastTimeFrame = DateTime.Now;
                    FPS = framesThisSecond;
                    framesThisSecond = 0;
                    form.Text = "JDX Engine - FPS: " + FPS.ToString() + "; Mesh2 Position: " + cv.Position.ToString() + "; Time Const: " + timeConstant.ToString();
                }
                framesThisSecond++;

                
            });

            jRndr.Dispose();
            inpt.Dispose();
        }


        private static bool MouseCam;
        private static float Speed;

        static void HandleInput(Jinput inpt, RenderForm rf, JDXRender jRndr, float timeConstant)
        {
            CameraViewport cv = jRndr.CameraViewports[0];
            float MoveSpeed = 0.02f * timeConstant;

            Dictionary<Key, bool> krd = inpt.Keys;
            if (krd.ContainsKey(Key.Escape) && krd[Key.Escape]) { Application.Exit(); }
            if (krd.ContainsKey(Key.W) && krd[Key.W]) { cv.Move(0f, 0f, MoveSpeed); }
            if (krd.ContainsKey(Key.S) && krd[Key.S]) { cv.Move(0f, 0f, -MoveSpeed); }
            if (krd.ContainsKey(Key.A) && krd[Key.A]) { cv.Move(-MoveSpeed, 0f, 0f); }
            if (krd.ContainsKey(Key.D) && krd[Key.D]) { cv.Move(MoveSpeed, 0f, 0f); }
            if (krd.ContainsKey(Key.UpArrow) && krd[Key.UpArrow]) { cv.Move(0f, MoveSpeed, 0f); }
            if (krd.ContainsKey(Key.Down) && krd[Key.Down]) { cv.Move(0f, -MoveSpeed, 0f); }
            if (krd.ContainsKey(Key.Space) && krd[Key.Space]) 
            {
                jRndr.Entities.Remove(gilsMesh);
                gilsMesh = jRndr.EntityFactory.LoadGilesMesh("SampleScene.gls", 0.1f);
                jRndr.Entities.Add(gilsMesh);
                gilsMesh.Move(0, 0, -3);
                jRndr.Entities.Add(gilsMesh);
            }

            if (rf.Focused)
            {
                MouseState ms = inpt.Mouse;
                if (ms.Buttons[1]) { MouseCam = !MouseCam; }

                if (MouseCam)
                {
                    System.Windows.Forms.Cursor.Hide();
                    cv.Rotate(-ms.Y * .001f, ms.X * .001f, 0f);
                    System.Windows.Forms.Cursor.Position =
                        new Point(rf.Width / 2, rf.Height / 2);
                    System.Windows.Forms.Cursor.Hide();
                } else { System.Windows.Forms.Cursor.Show(); }

                if (ms.Buttons[0])
                {
                    jRndr.Entities[1].Position = cv.Position; ;
                    jRndr.Entities[1].Rotation = jRndr.LastPickedDirection;
                    Speed = 0.02f;
                }

            } else { System.Windows.Forms.Cursor.Show(); }
            //
               
        }
    }
}